package com.wk.springboot.aop;

import com.wk.springboot.configuration.ExecutionType;
import com.wk.springboot.configuration.LocalMessageTransaction;
import com.wk.springboot.constant.CommonConstant;
import com.wk.springboot.dispatch.MessageDispatcher;
import com.wk.springboot.entity.LocalMessage;
import com.wk.springboot.mapper.LocalMessageMapper;
import com.wk.springboot.parse.EndpointConfigParser;
import com.wk.springboot.parse.PayloadBuilder;
import com.wk.springboot.parse.SpELParser;
import com.wk.springboot.service.MessageStoreService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

import static com.wk.springboot.constant.CommonConstant.MessageConstant.CONSUMER_SUCCESS;
import static com.wk.springboot.constant.CommonConstant.MessageConstant.SUCCESS;

@Aspect
@Component
public class LocalMessageAspect {
    
    @Autowired
    private MessageStoreService messageStoreService;

    @Autowired
    private LocalMessageMapper localMessageMapper;


    @Autowired
    MessageDispatcher messageDispatcher;

    @Autowired
    SpELParser spELParser;

    @Autowired
    PayloadBuilder payloadBuilder;

    @Autowired
    EndpointConfigParser endpointConfigParser;

    /**
     * 环绕通知，处理本地消息事务
     *
     *                    ┌──────────────┐
     *                    │ 业务方法执行   │
     *                    └──────┬───────┘
     *                           ↓
     *               ┌─────────────────────────┐
     *               │  @LocalMessageTransaction │
     *               └───────┬─────────┬───────┘
     *                       │         │
     *            ┌──────────┘         └──────────┐
     *            ↓ (execType=SYNC)      ↓ (execType=ASYNC)
     * ┌───────────────────────┐       ┌─────────────────────┐
     * │ 立即调用消息发送器       │       │ 写入待处理状态        │
     * │ 更新发送结果到数据库     │       │ 等待定时任务轮询处理   │
     * └───────────────────────┘       └─────────────────────┘
     * @param joinPoint 连接点
     * /
     */
    @Around("@annotation(localMessageTx)")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint, LocalMessageTransaction localMessageTx) throws Throwable {
        Object result = joinPoint.proceed();
        
        // 解析注解参数
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Object[] args = joinPoint.getArgs();
        
        // 构造消息实体
        LocalMessage message = getLocalMessage(localMessageTx, method, args);

        // 异步存储消息（需保证与业务事务一致）
        messageStoreService.saveMessageWithTransaction(message);
        if (message.getExecType().equals(ExecutionType.SYNC.name())) {
            // 同步执行消息发送器
            messageDispatcher.dispatch(message);
            // 同步更新发送结果到数据库
            localMessageMapper.updateStatus(message.getId(), SUCCESS);
        }

        
        return result;
    }

    private LocalMessage getLocalMessage(LocalMessageTransaction localMessageTx, Method method, Object[] args) throws Exception {
        LocalMessage message = new LocalMessage();
        message.setBizType(localMessageTx.bizType());
        message.setBizKey(spELParser.parseSpEL(localMessageTx.bizKeySpEL(), method, args));
        message.setContent(payloadBuilder.buildPayload(localMessageTx.payloadClass(), args));
        message.setEndpointType(localMessageTx.endpointType().name());
        message.setEndpointConfig(endpointConfigParser.parseEndpointConfig(
                localMessageTx, method, args
        ));
        message.setRetryCount(localMessageTx.retryCount());
        message.setCurrentRetryCount(1);
        message.setExecType(localMessageTx.execType().name());
        return message;
    }

    // 其他辅助方法...
}